#ifndef __BUFFER_H__
#define __BUFFER_H__

#ifdef __cplusplus
extern "C" {
#endif

// queue
struct losq_node_t
{
    uint32_t addr;
    struct losq_node_t *next;
};
struct losq_t
{
    struct losq_node_t *head;
    struct losq_node_t *tail;
};

struct los_buffer_t
{
    uint8_t *buffer;
    uint32_t size;
};

// fifo
struct los_fifo_t
{
    struct los_buffer_t buffer;
    uint32_t head;
    uint32_t tail;
    bool_t   wrap;
};

void losq_init(struct losq_t *q);
void losq_append(struct losq_t *q, struct losq_node_t *n);
void losq_remove(struct losq_t *q, struct losq_node_t *n);
void losq_enqueue(struct losq_t *q, struct losq_node_t *n);
struct losq_node_t* losq_dequeue(struct losq_t *q);

int los_fifo_init(struct los_fifo_t *fifo);
uint32_t los_fifo_push8(struct los_fifo_t *fifo, uint8_t data);
uint8_t los_fifo_pop8(struct los_fifo_t *fifo);
uint32_t los_fifo_push(struct los_fifo_t *fifo, uint32_t size, uint8_t *data);
uint32_t los_fifo_pop(struct los_fifo_t *fifo, uint32_t size, uint8_t *data);
uint32_t los_fifo_peek(struct los_fifo_t *fifo, uint32_t size, uint8_t *data);
uint32_t los_fifo_get_wbuf(struct los_fifo_t *fifo, uint8_t **data);
uint32_t los_fifo_get_rbuf(struct los_fifo_t *fifo, uint8_t **data);
uint32_t los_fifo_get_data_length(struct los_fifo_t *fifo);
uint32_t los_fifo_get_avail_length(struct los_fifo_t *fifo);

#ifdef __cplusplus
}
#endif

#endif
